/**
  \file TestCase_DawgSha1.cpp
  \author Francis Girard
  \date 28 october 2013
*/


/*
 *  Copyright (C) 2013, Francis Girard
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/config/SourcePrefix.h>

#include "polarssl/sha1.h"


class TestCase_DawgSha1 : public CPPUNIT_NS::TestFixture
{
  CPPUNIT_TEST_SUITE( TestCase_DawgSha1 );
  CPPUNIT_TEST( test_sha1_self_test );
  CPPUNIT_TEST( test_sha1_others );
  CPPUNIT_TEST_SUITE_END();

public:
  void setUp();
  void tearDown();

protected:
  void test_sha1_self_test();
  void test_sha1_others();
};
CPPUNIT_TEST_SUITE_REGISTRATION( TestCase_DawgSha1 );


void TestCase_DawgSha1::setUp()
{
}


void TestCase_DawgSha1::tearDown()
{
}


void TestCase_DawgSha1::test_sha1_self_test()
{
  int verbose = 0;
  int nOk = sha1_self_test(verbose);
  CPPUNIT_ASSERT_EQUAL( 0, nOk );
}


void TestCase_DawgSha1::test_sha1_others()
{
    const char* pAlphabet1 = "a";
    const char* pAlphabet2 = "b";
    const char* pAlphabet3 = "c";
    const char* pAlphabet4 = "d";
    const char* pAlphabet5 = "e";
    const char* pAlphabet6 = "f";
    const char* pAlphabet7 = "g";
    const char* pAlphabet8 = "h";
    const char* pAlphabet9 = "i";
    const char* pAlphabet10 = "j";
    const char* pAlphabet11 = "k";
    const char* pAlphabet12 = "l";
    const char* pAlphabet13 = "m";
    const char* pAlphabet14 = "n";
    const char* pAlphabet15 = "o";
    const char* pAlphabet16 = "p";
    const char* pAlphabet17 = "q";
    const char* pAlphabet18 = "r";
    const char* pAlphabet19 = "s";
    const char* pAlphabet20 = "t";
    const char* pAlphabet21 = "u";
    const char* pAlphabet22 = "v";
    const char* pAlphabet23 = "w";
    const char* pAlphabet24 = "x";
    const char* pAlphabet25 = "y";
    const char* pAlphabet26 = "z";
    const char* p2Letters1 = "ab";
    const char* p2Letters2 = "cd";
    const char* p2Letters3 = "ef";
    const char* p2Letters4 = "gh";
    const char* p2Letters5 = "ij";
    const char* p2Letters6 = "kl";
    const char* p2Letters7 = "mn";
    const char* p2Letters8 = "op";
    const char* p2Letters9 = "qr";
    const char* p2Letters10 = "st";
    const char* p2Letters11 = "uv";
    const char* p2Letters12 = "wx";
    const char* p2Letters13 = "yz";
    const char* pLoremIpsum1 = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy";
    const char* pLoremIpsum2 = "Lorem ipsum dolor sit amet, fonsectetuer adipiscing elit, sed diam nonummy";
    const char* pLoremIpsum3 = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, ed diam nonummy";

    const char* ppInputs[42] = { pAlphabet1,
                                 pAlphabet2,
                                 pAlphabet3,
                                 pAlphabet4,
                                 pAlphabet5,
                                 pAlphabet6,
                                 pAlphabet7,
                                 pAlphabet8,
                                 pAlphabet9,
                                 pAlphabet10,
                                 pAlphabet11,
                                 pAlphabet12,
                                 pAlphabet13,
                                 pAlphabet14,
                                 pAlphabet15,
                                 pAlphabet16,
                                 pAlphabet17,
                                 pAlphabet18,
                                 pAlphabet19,
                                 pAlphabet20,
                                 pAlphabet21,
                                 pAlphabet22,
                                 pAlphabet23,
                                 pAlphabet24,
                                 pAlphabet25,
                                 pAlphabet26,
                                 p2Letters1,
                                 p2Letters2,
                                 p2Letters3,
                                 p2Letters4,
                                 p2Letters5,
                                 p2Letters6,
                                 p2Letters7,
                                 p2Letters8,
                                 p2Letters9,
                                 p2Letters10,
                                 p2Letters11,
                                 p2Letters12,
                                 p2Letters13,
                                 pLoremIpsum1,
                                 pLoremIpsum2,
                                 pLoremIpsum3 };
    unsigned char pOutputs[840]; // 840 = 20 * 42
    unsigned char pOutput0[20];

    //
    // Initialize the outputs to 0 everywhere
    //
    bzero(pOutputs, sizeof(unsigned char)*840);
    bzero(pOutput0, sizeof(unsigned char)*20);

    //
    // Apply sha1 to all the inputs
    //
    unsigned char* pOutputCur = pOutputs;
    const char** ppInputsCur = ppInputs;
    const char** ppInputsEnd = ppInputsCur + 42;
    for ( ; ppInputsCur < ppInputsEnd; pOutputCur += 20, ppInputsCur += 1 )
    {
        sha1((const unsigned char*) *ppInputsCur, strlen(*ppInputsCur), pOutputCur);
    }

    //
    // Test that no output is 0 and that they are all unique
    //
    pOutputCur = pOutputs;
    unsigned char* pOutputEnd = pOutputCur + 840;
    unsigned char* pOutputLast = pOutputEnd - 20;
    for ( ; pOutputCur < pOutputLast; pOutputCur += 20 )
    {
        CPPUNIT_ASSERT( memcmp(pOutputCur, pOutput0, 20*sizeof(unsigned char)) != 0 );

        unsigned char* pOutputInsideCur = pOutputCur + 20;
        for ( ; pOutputInsideCur < pOutputEnd; pOutputInsideCur += 20 )
        {
            CPPUNIT_ASSERT( memcmp(pOutputCur, pOutputInsideCur, 20*sizeof(unsigned char)) != 0 );
        }
    }
}

